package com.xbongbong.paas.service.impl;

import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.vo.CallCenterOrgGetByCorpIdVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.service.CallCenterAgentStrategyService;
import com.xbongbong.paas.service.CallCenterOrganizationService;
import com.xbongbong.paas.service.CallCenterStatementService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CallCenterErrorCodeEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.callcenter.CallCenterConstant;
import com.xbongbong.saas.domain.entity.CallCenterAgentStrategyEntity;
import com.xbongbong.saas.domain.entity.CallCenterOrganizationEntity;
import com.xbongbong.saas.model.CallCenterAgentStrategyModel;
import com.xbongbong.saas.model.CallCenterOrganizationModel;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

/**
 * @author youli.chen
 * @version v1.0
 * @description: 话务中心坐席策略实现类
 * @date 2019/2/28 9:25
 * @since v1.0
 */
@Service("callCenterAgentStrategyService")
public class CallCenterAgentStrategyServiceImpl implements CallCenterAgentStrategyService {

    private static final Logger LOG = LoggerFactory.getLogger(CallCenterAgentStrategyServiceImpl.class);

    @Resource
    private CallCenterAgentStrategyModel callCenterAgentStrategyModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private CallCenterOrganizationService callCenterOrganizationService;
    @Resource
    private CallCenterOrganizationModel callCenterOrganizationModel;
    @Resource
    private CallCenterStatementService callCenterStatementService;

    /**
     * 获取当前激活的坐席套餐（没有则会保存一份默认的）
     *
     * @param corpid     公司id
     * @param moduleType 平台信息，参考CallCenterTypeEnum
     * @return
     * @throws XbbException
     */
    @Override
    public CallCenterAgentStrategyEntity getActiveStrategy(String corpid, Integer moduleType) throws XbbException {
        Map<String, Object> params = new HashMap<>(16);
        params.put("corpid", corpid);
        params.put("moduleType", moduleType);
        params.put("isActive", 1);
        params.put("del", DelEnum.NORMAL.getDel());
        params.put("start", 0);
        params.put("pageNum", 1);
        List<CallCenterAgentStrategyEntity> list = callCenterAgentStrategyModel.findEntitys(params);
        if (list.size() == 0) {
            // 当前公司还没有启用的套餐，设置一条默认的套餐
            CallCenterAgentStrategyEntity strategy = new CallCenterAgentStrategyEntity(corpid, moduleType);
            callCenterAgentStrategyModel.insert(strategy);
            return strategy;
        } else {
            return list.get(0);
        }
    }

    /**
     * 进行坐席月费自动扣缴
     *
     * @param corpid        公司id
     * @param moduleType    微应用类型
     * @param agentNameList 需要扣缴费用的坐席姓名队列
     * @param memo          备注
     * @return boolean 扣费是否成功
     * @throws XbbException 封装异常
     */
    @Override
    public boolean consume(String corpid, Integer moduleType, List<String> agentNameList, String memo) throws XbbException {
        if (agentNameList == null || agentNameList.isEmpty()) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301050);
        }
        if (!lock(corpid, moduleType)) {
            // 可能还有其他消费任务在执行
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301025);
        }

        CallCenterOrgGetByCorpIdVO org = callCenterOrganizationService.getByCorpId(corpid, moduleType);
        if (org == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
        }

        CallCenterAgentStrategyEntity strategy = getActiveStrategy(corpid, moduleType);
        BigDecimal cost = calculateResidualCost(strategy.getPrice(), agentNameList.size());
        if (cost.compareTo(org.getBalance()) > 0) {
            unlock(corpid, moduleType);
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301021);
        }
        boolean result = callCenterStatementService.consume(corpid, moduleType, cost, agentNameList, memo);
        if (!result) {
            unlock(corpid, moduleType);
            return false;
        }
        if (org.getPaidAgentNum() == null || org.getPaidAgentNum() < 0) {
            org.setPaidAgentNum(0);
        } else {
            org.setPaidAgentNum(org.getPaidAgentNum() + agentNameList.size());
        }

        org.setBalance(callCenterStatementService.checkBillBalance(corpid, moduleType));
        CallCenterOrganizationEntity orgEntity = new CallCenterOrganizationEntity();
        BeanUtils.copyProperties(org, orgEntity);
        if (callCenterOrganizationModel.update(orgEntity) > 0) {
            unlock(corpid, moduleType);
            return true;
        } else {
            unlock(corpid, moduleType);
            return false;
        }
    }

    /**
     * 计算剩余需要缴纳的坐席费用
     *
     * @param price    坐席单价
     * @param agentNum 需要缴费的坐席数
     * @return 需要缴纳的金额
     */
    @Override
    public BigDecimal calculateResidualCost(BigDecimal price, Integer agentNum) {
        Integer currentMonthDays = DateUtil.getCurrentMonthDays();
        // 剩余需要缴费的月比例
        double remainder = Double.parseDouble("" + (currentMonthDays - DateUtil.getTodayNumInMonth() + 1)) / currentMonthDays;
        return price.multiply(new BigDecimal(agentNum)).multiply(BigDecimal.valueOf(remainder));
    }

    /**
     * 上消费锁
     *
     * @param corpid     公司id
     * @param moduleType 微应用类型
     * @return 是否成功上锁
     * @author 章华隽
     * 创建时间：2018/3/30 下午4:09
     * 修改时间：
     * @version 3.20
     * @since 3.20
     */
    private boolean lock(String corpid, Integer moduleType) {
        String lock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_CONSUME_LOCK,
                corpid + StringConstant.COLON + moduleType);
        // 话务中心用户可以看到详情页的通话记录
        if (StringUtil.isNotEmpty(lock)) {
            return false;
        } else {
            paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_CONSUME_LOCK,
                    corpid + StringConstant.COLON + moduleType,
                    StringConstant.LOCKED,
                    RedisConstant.TINY_DURATION);
            return true;
        }
    }

    /**
     * 上消费锁
     *
     * @param corpid     公司id
     * @param moduleType 微应用类型
     * @return 是否成功上锁
     * @author 章华隽
     * 创建时间：2018/3/30 下午4:09
     * 修改时间：
     * @version 3.20
     * @since 3.20
     */
    private void unlock(String corpid, Integer moduleType) {
        paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_CONSUME_LOCK,
                corpid + StringConstant.COLON + moduleType);
    }
}
